﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MagicArenaFramework.GameObject.Components
{
    /// <summary>
    /// GoComponent is the base class for all components that make up game objects.
    /// It has three basic methods, Update, Draw and OnGui.
    /// However, to use this class you do not change these methods.
    /// Instead you should set the delegates UpdateDel, DrawDel and OnGuiDel.
    /// These delegates are called whenever isActive is true.
    /// 
    /// By default all components have the same priority with delegate methods.
    /// This can be changed by overriding the registerSelf methods to include a priority.
    /// 
    /// Note: You should not override the Update, Draw and OnGui methods unless you REALLY know what you are doing
    ///       It is easy to break the propogation of the calls through all objects if you do something wrong.
    ///       Stick to setting the delegates for most uses
    /// </summary>
    public abstract class GoComponent
    {
        public delegate void GoMethod(float dt);

        // TODO Decide is isActive should change registration of dels with parents
        public virtual bool isActive{get;set;}

        public virtual GoMethod UpdateDel{get;set;}
        public virtual GoMethod DrawDel { get; set; }
        public virtual GoMethod GuiDel { get; set; }

        public GoComposite Parent;
            

        public virtual void Update(float dt)
        {
            if (UpdateDel == null) throw new NotImplementedException();
            if (isActive) UpdateDel(dt);
        }

        public virtual void Draw(float dt)
        {
            if (DrawDel == null) throw new NotImplementedException();
            if (isActive) DrawDel(dt);
        }

        public virtual void OnGui(float dt)
        {
            if (GuiDel == null) throw new NotImplementedException();
            if (isActive) GuiDel(dt);
        }

        public virtual void Destroy()
        {
            if (Parent != null)
            {
                Parent.RemoveChild(this);
                UnRegisterSelf(Parent);
            }
            isActive = false;
        }

        #region Register delegates with parents
        public virtual void RegisterSelf(GoComposite parent)
        {
            if (parent == null) return;
            if (UpdateDel != null) parent.registerUpdate(Update);
            if (DrawDel != null) parent.registerDraw(Draw);
            if (GuiDel != null) parent.registerOnGui(OnGui);
            Parent = parent;
        }
        public virtual bool UnRegisterSelf(GoComposite parent)
        {
            if (parent == null) return false;
            bool rtn = false;
            if (UpdateDel != null) rtn |= parent.unregisterUpdate(Update);
            if (DrawDel != null) rtn |= parent.unregisterDraw(Draw);
            if (GuiDel != null) rtn |= parent.unregisterOnGui(OnGui);
            Parent = null;
            return rtn;
        }
        #endregion
    }

}
